
#include "linux_def.h"
#include "core.h"
#include "event.h"

#define SOCKLEN	512

static int enable_accept_events(cycle_t *cycle);
static int disable_accept_events(cycle_t *cycle);
static void close_accepted_connection(connection_t *c);

void event_accept(event_t *ev)
{
	int	s;
	socklen_t	socklen;
	log_t		*log;

	event_t	*rev, *wev;
	listening_t	*ls;
	connection_t *c, *lc;
	char	sa[SOCKLEN];

	lc = ev->data;
	ls = lc->listening;
	ev->ready = 0;

		socklen = SOCKLEN;
		s = accept(lc->fd, (struct sockaddr*)sa, &socklen); 
		if (s == -1){
			if (errno == EAGAIN)
				return;
			return;
		}
		
		c = get_connection(s);
		if (c == NULL){
			printf("%s, %d, %s.\n", __FILE__, __LINE__, __func__);
			close(s);
			return;
		}

		c->pool = create_pool(2046, ev->log);
		if (c->pool == NULL){
			printf("Error: %s == %d, %s", __FILE__, __LINE__, __func__);
			close_accepted_connection(c);
			return;
		}
		c->sockaddr  = palloc(c->pool, socklen);
		if (c->sockaddr == NULL){
			printf("Error: %s == %d, %s", __FILE__, __LINE__, __func__);
			close_accepted_connection(c);
			return;
		}

		memcpy(c->sockaddr, sa, socklen);	

		//设置新建连接为非阻塞
		//如果为阻塞的话直接读数据
		if (set_nonblocking(s) == -1){
			fprintf(stderr, "set_nonblocking() failed.\n");
			close_accepted_connection(c);
			return;
		}

		c->recv = g_recv;
		c->send = g_send;
		c->recv_chain = g_recv_chain;
		c->send_chain = g_send_chain;

		c->listening = ls;
		c->socklen = socklen;

		rev = c->read;
		wev = c->write;

		rev->ready = 1;
		wev->ready = 1;
	
		rev->handler = request_handler;

		c->number = atomic_fetch_add(connection_counter_ptr, 1);

		if (epoll_add_event(rev, READ_EVENT, CLEAR_EVENT) == E_FAIL){
			fprintf(stderr, "epoll_add_connection( c ) failed.\n");
			epoll_del_event(rev, READ_EVENT, 0);
			return;
		}

		event_add_timer(rev, 10000);

		if (verbose)
			printf("%s == %d, %s\n", __FILE__, __LINE__, __func__);

//	}while(ev->available)

	return;
}




static void close_accepted_connection(connection_t *c)
{
	int	fd;
	
	free_connection(c);

	fd = c->fd;
	c->fd = -1;
	close(fd);
}


int trylock_accept_mutex(cycle_t *cycle)
{
	if (shmtx_trylock(&accept_mutex)){
		if (enable_accept_events(cycle) == E_FAIL){
			fprintf(stderr, "enable_accept_events( ) failed.\n");
			shmtx_unlock(&accept_mutex);
		}

		accept_events = 0;
		accept_mutex_held = 1;
		
		return E_OK;
	}

	if (accept_mutex_held){
		if (disable_accept_events(cycle) == E_FAIL)
			return E_FAIL;

		accept_mutex_held = 0;
	}

	return E_OK;
}


static int enable_accept_events(cycle_t *cycle)
{
	int	i;
	listening_t	*ls;
	connection_t	*c;

	ls = cycle->listening.elts;
	for (i=0; i<cycle->listening.nelts; i++){
		c  = ls[i].connection;
		if (epoll_add_event(c->read, READ_EVENT, 0) == -1)
			return E_FAIL;
	}

	return E_OK;
}
static int disable_accept_events(cycle_t *cycle)
{
	int	i;
	listening_t	*ls;
	connection_t	*c;

	ls = cycle->listening.elts;
	for (i=0; i<cycle->listening.nelts; i++){
		c = ls[i].connection;
	
		if (!c->read->active)
			continue;

		if (epoll_del_event(c->read, READ_EVENT, DISABLE_EVENT) == -1)
			return E_FAIL;
	}

	return E_OK;
}
